import datetime
import pandas as pd
from functools import partial
def subtime_minute(t1,t0):
    return (t1.hour-t0.hour)*60+t1.minute-t0.minute
def addtime_mintue(t0,m):
    m=m+t0.minute
    return [t0.hour+m//60,m%60]
def time2datetime(t):
    return datetime.datetime(year=2000,month=1,day=1,hour=t.hour,minute=t.minute,second=t.second)
class asset_returns:
    def __init__(self,timekey=None,asset=None,period="1m"):
        """
        Args:
            timekey: calc by timekey
            asset: curr asset
            period: type
                1m: 1 minutes
                nm:n min
                1h: 60min
                1d: 1day
                1w:1 weeky
        """
        self.assets=[]
        self.timekey=timekey
        self.period=period
        if not timekey:
            t={}
            t["timekey"]=timekey
            t["asset"]=asset
            t["asset_limit"]=0
            t["return"]=0
            self.assets.append(asset)
        self.tradetime = [[datetime.time(21, 0, 0), datetime.time(23, 0, 0)],
                          [datetime.time(9, 0, 0), datetime.time(10, 15, 0)],
                          [datetime.time(10, 30, 0), datetime.time(11, 30, 0)],
                          [datetime.time(13, 30, 0), datetime.time(15, 0, 0)]
                          ]
        self.gaptime = dict(
            nightrest=[datetime.time(23, 0, 0), datetime.time(9, 0, 0)]
            , amrest=[datetime.time(10, 15, 0), datetime.time(10, 30, 0)]
            , noonrest=[datetime.time(11, 30, 0), datetime.time(13, 30, 0)]
        )
        self.gettimekey=partial(self.gettimekeybyperiod,period)
    def setdata(self,timekey,asset,asset_limit=None,r=None):
        key=self.gettimekey(timekey)
        t = {}
        t["timekey"] = key
        t["asset"] = asset
        if not timekey:
            t["asset_limit"]=asset
            t["return"]=0
            self.assets.append(asset)
        else:
            if self.timekey==key:
                if len(self.assets)>=2:
                    p0=self.assets[-2]
                    if asset_limit:
                        t["asset_limit"] = asset_limit
                    else:
                        t["asset_limit"] = asset
                    if r:
                        t["return"] = r
                    else:
                        t["return"] = (asset - p0["asset"]) / p0["asset"]
                    self.assets[-1]=t
            else:
                p0=self.assets[-1]
                if asset_limit:
                    t["asset_limit"] = asset_limit
                else:
                    t["pl"] = asset
                if r:
                    t["return"] = r
                else:
                    t["return"] = (asset - p0["asset"]) / p0["asset"]
                self.assets.append(t)
        self.timekey = key
    def gettimekeybyperiod(self,period,t):
        typep=period[-1]
        n=period[:-1]
        if typep=="m":
            return self.gettimekeybymin(t,n)
        elif typep=="h":
            n=n*60
            return self.gettimekeybymin(t,n)
        else:
            return self.getdaytimkey(t)
    def getdaytimkey(self,a):
        hour=a.hour
        if hour >=20:
            return datetime.datetime(a.year, a.month, a.day+1)
        else:
            return datetime.datetime(a.year, a.month, a.day)
    def gettimekeybymin(self,a,m):
        time = a.time()
        n = -1
        fromtime = [time.hour, time.minute]
        test = False
        for i in self.tradetime:
            test = (time >= i[0]) and (time < i[1])
            if test:
                delta = subtime_minute(time, i[0])
                if n >= 0:
                    delta = delta + self.remainder[n]
                delta = delta - delta % m
                fromtime = addtime_mintue(i[0], delta)
                break
            else:
                n = n + 1
        b = datetime.datetime(a.year, a.month, a.day, fromtime[0], fromtime[1])
        return b
    def getdataframe(self):
        b = pd.DataFrame(self.assets)
        b.index=b["timekey"]
    def convert(self,period):
        rst=[]
        getkey=partial(self.gettimekeybyperiod,period)
        timekey0=None
        pl=0
        for i in self.assets:
            timekey = i["timekey"]
            key = getkey(timekey)
            if timekey0:
                if timekey0 == key:
                    if len(rst) >= 2:
                        p0 = rst[-2]
                        t["asset_limit"] = min(pl,  p0["asset_limit"])
                        t["return"] = (i["asset"] - p0["asset"]) / p0["asset"]
                        self.assets[-1] = t
                        pl=t["asset_limit"]
                else:
                    t = {}
                    t["timekey"] = key
                    t["asset"] = i["asset"]
                    t["asset_limit"] = i["asset_limit"]
                    t["return"] = (i["asset"] - p0["asset"]) / p0["asset"]
                    pl=i["asset_limit"]
                    self.assets.append(t)
            else:
                t = {}
                t["timekey"] = key
                t["asset"] = i["asset"]
                t["asset_limit"]=i["asset_limit"]
                t["return"]=0
                rst.append(t)
                pl=i["asset_limit"]
            timekey0 = key
        return rst